#include "zvector.h"
#include "zmath.h"
#include <stdlib.h>

// create vector with originCapacity, 
// the originCapacity's value must more than or equal to zero
// the initalize m_List's memory size is the nearest number who is greater than or equal to 2's pow
//		such as: oroginCapacity = 0, m_List's size = 2 * (sizeof(void *))
//		such as: oroginCapacity = 4, m_List's size = 4 * (sizeof(void *))
//		such as: oroginCapacity = 9, m_List's size = 16 * (sizeof(void *))
//      and so on
int zvector_create(zvector ** obj, int originCapacity)
{
	//1 make sure the obj is not null, and originCapacity is more than 0 or equal to 0
	if (obj == NULL)
	{
		return -1;
	}
	if (originCapacity < 0)
	{
		return -1;
	}

	//2 init memory of *obj's pointing
	zvector * p_obj = (zvector *)calloc(1, sizeof(zvector));
	if (p_obj == NULL)
	{
		return -1;
	}

	//3 get the 2's pow val which is morethan or equal to originCapacity, if originCapacity is equal to 0, then put it to 2!
	int capacity = zmath_powoftwo(originCapacity);

	//4 init memory of m_List's pointing
	p_obj->m_List = (void **)calloc(capacity, sizeof(void *));
	if (p_obj->m_List == NULL)
	{
		free(p_obj);
		p_obj = NULL;
		return -1;
	}

	//5 set value of para
	p_obj->m_Count = 0;
	p_obj->m_Capacity = capacity;
	*obj = p_obj;

	return 0;
}

// add one item's ref(address) to the zvector's last
int zvector_add(zvector * obj, void * item)
{
	if (obj == NULL)
	{
		return -1;
	}

	//1. m_List[obj->m_Count] = item 
	//2. m_List = realloc(..         

	if (obj->m_Count >= obj->m_Capacity)
	{
		int t_Capacity = obj->m_Capacity;
		t_Capacity = zmath_powoftwo(t_Capacity + 1);

		// need extend mem
		obj->m_List = realloc(obj->m_List, t_Capacity * (sizeof(void *)));
		obj->m_Capacity = t_Capacity;
	}
	else
	{
		// unchange m_List
	}

	obj->m_List[obj->m_Count] = item;
	obj->m_Count++;

	return 0;
}

// destroy the obj pointing memory, and set *obj to NULL
// pay attention to every address's memory, you must free them before call this!
int zvector_destroy(zvector ** obj)
{
	if (obj == NULL)
	{
		return -1;
	}

	if ((*obj)->m_List != NULL)
	{
		free((*obj)->m_List);
		(*obj)->m_List = NULL;
	}
	free(*obj);
	*obj = NULL;

	return 0;
}